package cn.lili.common.utils;

import io.reactivex.rxjava3.internal.util.LinkedArrayList;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 对象属性复制
 *
 * @author Chopper
 */
public class BeanUtil {

    private BeanUtil() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 复制属性
     *
     * @param objectFrom 源自对象
     * @param objectTo   复制给对象
     */
    public static void copyProperties(Object objectFrom, Object objectTo) {
        BeanUtils.copyProperties(objectFrom, objectTo);
    }


    /**
     * 获取属性名数组
     *
     * @param o 获取字段的对象
     * @return 返回各个字段
     */
    public static String[] getFiledName(Object o) {
        Field[] fields = o.getClass().getDeclaredFields();
        Field[] superFields = o.getClass().getSuperclass().getDeclaredFields();
        String[] fieldNames = new String[fields.length + superFields.length];
        int index = 0;
        for (Field field : fields) {
            fieldNames[index] = field.getName();
            index++;
        }
        for (Field superField : superFields) {
            if ("id".equals(superField.getName())) {
                continue;
            }
            fieldNames[index] = superField.getName();
            index++;
        }
        return fieldNames;
    }

    /**
     * 根据属性名获取属性值
     *
     * @param o         对象
     * @param fieldName 属性名
     * @return 属性值
     */
    public static Object getFieldValueByName(Object o, String fieldName) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter);
            return method.invoke(o);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 批量获取属性结果
     *
     * @param o         对象
     * @param fieldName 属性名
     * @return 属性值
     */
    public static List<Object> getFieldsValueByName(Object o, String... fieldName) {
        //收集结果
        List<Object> result = new LinkedList<>();

        //根据字段获取属性
        for (String field : fieldName) {
            try {
                String firstLetter = field.substring(0, 1).toUpperCase();
                String getter = "get" + firstLetter + field.substring(1);
                Method method = o.getClass().getMethod(getter);
                result.add(method.invoke(o));
            } catch (Exception e) {
                //如果没有get方法，则增加空结果
                result.add(null);
            }
        }

        return result;

    }


    /**
     * 将对象转换为key value
     * A=a&B=b&C=c 格式
     *
     * @param object 对象
     * @return 格式化结果
     */
    public static String formatKeyValuePair(Object object) {
        //准备接受的字符串
        StringBuilder stringBuffer = new StringBuilder();
        //获取对象字段
        String[] fieldNames = BeanUtil.getFiledName(object);
        //遍历所有属性
        for (int j = 0; j < fieldNames.length; j++) {
            //不是第一个并且不是最后一个，拼接&
            if (j != 0) {
                stringBuffer.append("&");
            }
            //获取属性的名字
            String key = fieldNames[j];
            //获取值
            Object value = BeanUtil.getFieldValueByName(object, key);
            assert value != null;
            stringBuffer.append(key).append("=").append(value.toString());
        }
        return stringBuffer.toString();
    }

    /**
     * key value键值对 转换为 对象
     * A=a&B=b&C=c 格式 转换为对象
     *
     * @param str 对象字符串
     * @param t   范型
     * @param <T> 范型
     * @return 格式化结果
     */
    public static <T> T formatKeyValuePair(String str, T t) {
        //填写对参数键值对
        String[] params = str.split("&");

        //获取对象字段
        String[] fieldNames = BeanUtil.getFiledName(t);

        try {
            //循环每个参数
            for (String param : params) {
                String[] keyValues = param.split("=");
                for (String fieldName : fieldNames) {
                    if (fieldName.equals(keyValues[0])) {
                        Field field = t.getClass().getDeclaredField(fieldName);
                        field.setAccessible(true);
                        //长度为2 才转换，否则不转
                        if (keyValues.length == 2) {
                            field.set(t, keyValues[1]);
                        }
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

}
